package com.micrometa.km.ui.components.tree;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.io.IOException;

import javax.swing.DropMode;
import javax.swing.JTree;

import org.pushingpixels.lafwidget.LafWidget;

public class FileTree extends JTree {
	private static final long serialVersionUID = 1L;

	public FileTree(FileTreeNode root) {
		super(root);
		this.setRootVisible(false);
		this.setCellRenderer(new FileTreeCellRenderer());
		this.setDropMode(DropMode.ON);
		this.setDragEnabled(true);
		DragSource dragSource = DragSource.getDefaultDragSource();
		dragSource.createDefaultDragGestureRecognizer(this,
				DnDConstants.ACTION_COPY_OR_MOVE,
				new DJTreeDragGestureListener());
		this.setSelectionRow(100);
		this.putClientProperty(LafWidget.TREE_AUTO_DND_SUPPORT, Boolean.TRUE);
	}

	private class DJTreeDragGestureListener implements DragGestureListener {
		public void dragGestureRecognized(DragGestureEvent dge) {
			FileTree tree = (FileTree) dge.getComponent();
			if (tree.getSelectionPath() != null) {
				FileTreeNode selection = (FileTreeNode) tree.getSelectionPath()
						.getLastPathComponent();
				DJTreeTransferable dtransferable = new DJTreeTransferable(
						selection);
				dge.startDrag(DragSource.DefaultCopyDrop, dtransferable,
						new DJTreeDragSourceListener());
			}
		}

	}

	private class DJTreeTransferable implements Transferable {
		private FileTreeNode dtnode;

		public DJTreeTransferable(FileTreeNode dtnode) {
			this.dtnode = dtnode;
		}

		public DataFlavor[] getTransferDataFlavors() {
			//在DJTreeDragSourceListener.drop()中，
			//如果是DataFlavor.stringFlavor类型的DragSource，
			//则是我们所要的FileTreeNode。
			return new DataFlavor[] { DataFlavor.stringFlavor };
		}

		public boolean isDataFlavorSupported(DataFlavor flavor) {
			if (dtnode.getChildCount() >= 0) {
				return true;
			}
			return false;
		}

		public Object getTransferData(DataFlavor flavor)
				throws UnsupportedFlavorException, IOException {
			return dtnode;
		}

	}

	private class DJTreeDragSourceListener implements DragSourceListener {

		public void dragEnter(DragSourceDragEvent dsde) {
			DragSourceContext context = dsde.getDragSourceContext();
			int dropAction = dsde.getDropAction();
			if ((dropAction & DnDConstants.ACTION_COPY) != 0) {
				context.setCursor(DragSource.DefaultCopyDrop);
			} else if ((dropAction & DnDConstants.ACTION_MOVE) != 0) {
				context.setCursor(DragSource.DefaultMoveDrop);
			} else {
				context.setCursor(DragSource.DefaultCopyNoDrop);
			}
		}

		public void dragOver(DragSourceDragEvent dsde) {

		}

		public void dropActionChanged(DragSourceDragEvent dsde) {
		}

		public void dragExit(DragSourceEvent dse) {
		}

		public void dragDropEnd(DragSourceDropEvent dsde) {
			if (!dsde.getDropSuccess())
				return;
			int dropAction = dsde.getDropAction();
			FileTree dtree = ((FileTree) (dsde.getDragSourceContext()
					.getComponent()));
			if (dropAction == DnDConstants.ACTION_MOVE) {
				try {
					// if the successful action is move ,remove the originally
					// node
					FileTreeNode snode = (FileTreeNode) dsde
							.getDragSourceContext().getTransferable()
							.getTransferData(DataFlavor.stringFlavor);
					snode.removeFromParent();
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
			dtree.updateUI();
		}
	}

}
